package refactoringtofuturetask.ui;

import java.util.Iterator;
import java.util.List;

import org.eclipse.jdt.internal.corext.refactoring.ParameterInfo;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.dialogs.TextFieldNavigationHandler;
import org.eclipse.jdt.internal.ui.javaeditor.JavaSourceViewer;
import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
import org.eclipse.jdt.internal.ui.refactoring.ChangeParametersControl;
import org.eclipse.jdt.internal.ui.refactoring.IParameterListChangeListener;
import org.eclipse.jdt.internal.ui.util.RowLayouter;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jdt.ui.text.JavaSourceViewerConfiguration;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

import refactoringtofuturetask.refactorings.ConvertToFutureTaskRefactoring;
import refactoringtofuturetask.util.FTRefactoringMessages;

public class ConvertToFutureTaskInputPage extends UserInputWizardPage {

	public static final String PAGE_NAME = "ConvertToFutureTaskInputPage";//$NON-NLS-1$

	private ConvertToFutureTaskRefactoring fRefactoring;
	private Text fTextField;
	private boolean fFirstTime;
	private JavaSourceViewer fSignaturePreview;
	private Document fSignaturePreviewDocument;
	private IDialogSettings fSettings;

	private static final String DESCRIPTION = "Enter new class name";
	private static final String THROW_RUNTIME_EXCEPTIONS = "ThrowRuntimeExceptions"; //$NON-NLS-1$
	private static final String GENERATE_JAVADOC = "GenerateJavadoc"; //$NON-NLS-1$

	public ConvertToFutureTaskInputPage() {
		super(PAGE_NAME);
		setImageDescriptor(JavaPluginImages.DESC_WIZBAN_REFACTOR_CU);
		setDescription(DESCRIPTION);
		fFirstTime = true;
		fSignaturePreviewDocument = new Document();
	}

	public void createControl(Composite parent) {
		fRefactoring = (ConvertToFutureTaskRefactoring) getRefactoring();
		loadSettings();

		Composite result = new Composite(parent, SWT.NONE);
		setControl(result);
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		result.setLayout(layout);
		RowLayouter layouter = new RowLayouter(2);
		GridData gd = null;

		initializeDialogUnits(result);

		Label label = new Label(result, SWT.NONE);
		label.setText(getLabelText());

		fTextField = createTextInputField(result, SWT.BORDER);
		fTextField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		layouter.perform(label, fTextField, 1);

		if (!fRefactoring.getParameterInfos().isEmpty()) {
			ChangeParametersControl cp = new ChangeParametersControl(
					result,
					SWT.NONE,
					FTRefactoringMessages.ConvertToFutureTaskInputPage_parameters,
					new IParameterListChangeListener() {
						public void parameterChanged(ParameterInfo parameter) {
							parameterModified();
						}

						public void parameterListChanged() {
							parameterModified();
						}

						public void parameterAdded(ParameterInfo parameter) {
							// updatePreview(getText());
						}
					}, ChangeParametersControl.Mode.EXTRACT_METHOD);
			gd = new GridData(GridData.FILL_BOTH);
			gd.horizontalSpan = 2;
			cp.setLayoutData(gd);
			cp.setInput(fRefactoring.getParameterInfos());
		}

		// Button checkBox= new Button(result, SWT.CHECK);
		// checkBox.setText(RefactoringMessages.ExtractMethodInputPage_throwRuntimeExceptions);
		// checkBox.setSelection(fSettings.getBoolean(THROW_RUNTIME_EXCEPTIONS));
		// checkBox.addSelectionListener(new SelectionAdapter() {
		// @Override
		// public void widgetSelected(SelectionEvent e) {
		// setRethrowRuntimeException(((Button)e.widget).getSelection());
		// }
		// });
		// layouter.perform(checkBox);
		//
		// checkBox= new Button(result, SWT.CHECK);
		// checkBox.setText(RefactoringMessages.ExtractMethodInputPage_generateJavadocComment);
		// boolean generate= computeGenerateJavadoc();
		// setGenerateJavadoc(generate);
		// checkBox.setSelection(generate);
		// checkBox.addSelectionListener(new SelectionAdapter() {
		// @Override
		// public void widgetSelected(SelectionEvent e) {
		// setGenerateJavadoc(((Button)e.widget).getSelection());
		// }
		// });
		// layouter.perform(checkBox);

		label = new Label(result, SWT.SEPARATOR | SWT.HORIZONTAL);
		label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		layouter.perform(label);

		createSignaturePreview(result, layouter);

		Dialog.applyDialogFont(result);
	}

	private Text createTextInputField(Composite parent, int style) {
		Text result = new Text(parent, style);
		result.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				textModified(getText());
			}
		});
		TextFieldNavigationHandler.install(result);
		return result;
	}

	private String getText() {
		if (fTextField == null)
			return null;
		return fTextField.getText();
	}

	private String getLabelText() {
		return FTRefactoringMessages.ConvertToFutureTaskInputPage_label_text;
	}

	private void setRethrowRuntimeException(boolean value) {
		fSettings.put(THROW_RUNTIME_EXCEPTIONS, value);
		// fRefactoring.setThrowRuntimeExceptions(value);
		// updatePreview(getText());
	}

	// private boolean computeGenerateJavadoc() {
	// boolean result= fRefactoring.getGenerateJavadoc();
	// if (result)
	// return result;
	// return fSettings.getBoolean(GENERATE_JAVADOC);
	// }
	//
	// private void setGenerateJavadoc(boolean value) {
	// fSettings.put(GENERATE_JAVADOC, value);
	// fRefactoring.setGenerateJavadoc(value);
	// }

	private void createSignaturePreview(Composite composite,
			RowLayouter layouter) {
		Label previewLabel = new Label(composite, SWT.NONE);
		previewLabel
				.setText(FTRefactoringMessages.ConvertToFutureTaskInputPage_signature_preview);
		layouter.perform(previewLabel);

		IPreferenceStore store = JavaPlugin.getDefault()
				.getCombinedPreferenceStore();
		fSignaturePreview = new JavaSourceViewer(composite, null, null, false,
				SWT.READ_ONLY | SWT.V_SCROLL | SWT.WRAP /* | SWT.BORDER */,
				store);
		fSignaturePreview.configure(new JavaSourceViewerConfiguration(
				JavaPlugin.getDefault().getJavaTextTools().getColorManager(),
				store, null, null));
		fSignaturePreview.getTextWidget().setFont(
				JFaceResources.getFont(PreferenceConstants.EDITOR_TEXT_FONT));
		fSignaturePreview.adaptBackgroundColor(composite);
		fSignaturePreview.setDocument(fSignaturePreviewDocument);
		fSignaturePreview.setEditable(false);

		// Layouting problems with wrapped text: see
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=9866
		Control signaturePreviewControl = fSignaturePreview.getControl();
		PixelConverter pixelConverter = new PixelConverter(
				signaturePreviewControl);
		GridData gdata = new GridData(GridData.FILL_BOTH);
		gdata.widthHint = pixelConverter.convertWidthInCharsToPixels(50);
		gdata.heightHint = pixelConverter.convertHeightInCharsToPixels(2);
		signaturePreviewControl.setLayoutData(gdata);
		layouter.perform(signaturePreviewControl);
	}

	// private void updatePreview(String text) {
	// if (fSignaturePreview == null)
	// return;
	//
	// if (text.length() == 0)
	//			text= "someMethodName";			 //$NON-NLS-1$
	//
	// int top= fSignaturePreview.getTextWidget().getTopPixel();
	// String signature;
	// try {
	// signature= fRefactoring.getSignature(text);
	// } catch (IllegalArgumentException e) {
	//			signature= ""; //$NON-NLS-1$
	// }
	// fSignaturePreviewDocument.set(signature);
	// fSignaturePreview.getTextWidget().setTopPixel(top);
	// }

	private void loadSettings() {
		fSettings = getDialogSettings().getSection(
				ConvertToFutureTaskWizard.DIALOG_SETTING_SECTION);
		if (fSettings == null) {
			fSettings = getDialogSettings().addNewSection(
					ConvertToFutureTaskWizard.DIALOG_SETTING_SECTION);
			fSettings.put(THROW_RUNTIME_EXCEPTIONS, false);
			fSettings
					.put(GENERATE_JAVADOC,
							JavaPreferencesSettings
									.getCodeGenerationSettings(fRefactoring
											.getCompilationUnit()
											.getJavaProject()).createComments);
		}
		fRefactoring.setThrowRuntimeExceptions(fSettings
				.getBoolean(THROW_RUNTIME_EXCEPTIONS));
	}

	// ---- Input validation
	// ------------------------------------------------------

	@Override
	public void setVisible(boolean visible) {
		if (visible) {
			if (fFirstTime) {
				fFirstTime = false;
				setPageComplete(false);
				// updatePreview(getText());
				fTextField.setFocus();
			} else {
				setPageComplete(validatePage(true));
			}
		}
		super.setVisible(visible);
	}

	private void textModified(String text) {
		fRefactoring.setMethodName(text);
		RefactoringStatus status = validatePage(true);
		if (!status.hasFatalError()) {
			// updatePreview(text);
		} else {
			fSignaturePreviewDocument.set(""); //$NON-NLS-1$
		}
		setPageComplete(status);
	}

	private void parameterModified() {
		// updatePreview(getText());
		setPageComplete(validatePage(false));
	}

	private RefactoringStatus validatePage(boolean text) {
		RefactoringStatus result = new RefactoringStatus();
		if (text) {
			result.merge(validateMethodName());
			result.merge(validateParameters());
		} else {
			result.merge(validateParameters());
			result.merge(validateMethodName());
		}
		return result;
	}

	private RefactoringStatus validateMethodName() {
		RefactoringStatus result = new RefactoringStatus();
		String text = getText();
		if ("".equals(text)) { //$NON-NLS-1$
			result.addFatalError(FTRefactoringMessages.ConvertToFutureTaskInputPage_validation_emptyClassName);
			return result;
		}
		result.merge(fRefactoring.checkClassName());
		return result;
	}

	private RefactoringStatus validateParameters() {
		RefactoringStatus result = new RefactoringStatus();
		List<ParameterInfo> parameters = fRefactoring.getParameterInfos();
		for (Iterator<ParameterInfo> iter = parameters.iterator(); iter
				.hasNext();) {
			ParameterInfo info = iter.next();
			if ("".equals(info.getNewName())) { //$NON-NLS-1$
				result.addFatalError(FTRefactoringMessages.ConvertToFutureTaskInputPage_validation_emptyParameterName);
				return result;
			}
		}
		result.merge(fRefactoring.checkParameterNames());
		result.merge(fRefactoring.checkVarargOrder());
		return result;
	}
}
